Skip to content

refactor/nullable repo key#3826

Open
fiftin wants to merge 5 commits intodevelopfrom
refactor/nullable_repo_key
Open

refactor/nullable repo key#3826
fiftin wants to merge 5 commits intodevelopfrom
refactor/nullable_repo_key

Conversation

@fiftin
Copy link
Copy Markdown
Collaborator

@fiftin fiftin commented May 3, 2026

  • refactor(repos): allow nil for key id
  • feat(migration): nullable key column in repo

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (PR 3826)

Outcome: One medium finding: nullable ssh_key_id without defensive checks on Repository.SSHKey allows authenticated denial-of-service (process panic) on git operations and unsafe behavior where code assumes a non-nil key.

Details: ValidateRepository skips key validation when SSHKeyID is nil, but several paths still dereference SSHKey (notably GoGitClient.getAuthMethod and Repository.GetGitURL for HTTP). Any project user who can create/update repositories can omit ssh_key_id and trigger panics or inconsistent auth when the scheduler/runner hits git.

No separate high/critical authz bypass or injection issue was confirmed in the reviewed diff; runner/task secret mapping changes correctly gate on SSHKeyID != nil.


Slack summary: PR 3826 security review: 1 medium — nullable repo SSH key + missing nil guards → DoS (panic) on git paths; fix by guarding SSHKey == nil before use or rejecting null key for remote repos in validation.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread db_lib/GoGitClient.go
@@ -42,12 +42,14 @@ func (c GoGitClient) getAuthMethod(r GitRepository) (transport.AuthMethod, error
switch r.Repository.SSHKey.Type {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: Medium — denial of service (availability)

ValidateRepository returns without loading a key when SSHKeyID is nil, so Repository.SSHKey can be nil at runtime for normal API-created repos. This function still does switch r.Repository.SSHKey.Type, which panics on nil before any auth branch. Any authenticated user who can add a remote repository without ssh_key_id can cause the server process to crash when schedules, tasks, or branch listing run git via the default go-git client.

Impact: Process panic → denial of service for the Semaphore instance.

Comment thread db/Repository.go
SSHKey *AccessKey `db:"-" json:"-" backup:"-"`
}

func (r Repository) ClearCache() error {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: Medium — denial of service / unsafe git URL handling

For RepositoryHTTP, GetGitURL(false) uses r.SSHKey.Type and r.SSHKey.LoginPassword without checking SSHKey != nil. With nullable ssh_key_id, SSHKey can be nil when this runs (e.g. cmd-git GetGitURL(false)), causing a nil pointer panic or undefined behavior.

Impact: Same DoS class as GoGitClient.getAuthMethod; also risks incorrect clone URLs if execution continued without crashing.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a0dc9d091

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread db_lib/GoGitClient.go
@@ -42,12 +42,14 @@ func (c GoGitClient) getAuthMethod(r GitRepository) (transport.AuthMethod, error
switch r.Repository.SSHKey.Type {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard nil SSH key before selecting auth method

Repository.SSHKey is now nullable, but getAuthMethod immediately dereferences it in switch r.Repository.SSHKey.Type. For repositories created without a key (e.g., public HTTPS repos), any go-git operation that calls this path will panic before reaching the later nil check, so clone/pull/fetch can crash instead of using unauthenticated access.

Useful? React with 👍 / 👎.

@@ -0,0 +1 @@
-- do nothing No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rename 2.18.7 rollback file to expected pattern

The rollback loader resolves files as v<version>.err.sql (via getVersionErrPath), so v.2.18.7.err.sql is never discovered. That means rollback handling for migration 2.18.7 silently skips its SQL, which can leave schema changes in place while rollback flow proceeds as if it succeeded.

Useful? React with 👍 / 👎.

Comment thread db/sql/migration.go
Comment on lines +193 to +195
if d.GetDialect() == util.DbDriverSQLite {
_, err = d.Sql().Exec("PRAGMA foreign_keys = OFF")
if err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore SQLite foreign_keys when migration exits early

SQLite foreign keys are turned off before starting the transaction, but turned back on only after a successful commit. Several earlier return paths in this function (e.g., begin failure, pre/post-apply errors, insert failure) bypass the re-enable step, so a migration error can leave the process with foreign key enforcement disabled.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (PR #3826)

Verdict: One high-confidence availability issue was introduced in db_lib/GoGitClient.go when Repository.SSHKey became nullable: getAuthMethod still switches on r.Repository.SSHKey.Type before verifying the pointer, so a repository with no SSH key (nullable ssh_key_id) and a non-local URL causes a nil pointer dereference (panic) when the built-in go_git client runs (clone/pull/etc.). That is a denial-of-service risk for the runner/task process, not a confidentiality bypass.

Not treated as security findings: SQLite PRAGMA foreign_keys toggles during migration are migration mechanics; runner/API changes around optional keys align with the schema change and do not by themselves expose new authz bypasses. CmdGitClient safely no-ops Destroy() on a zero AccessKeyInstallation.

No prior thread IDs were available in-repo; cleanup_previous was used to reconcile earlier automation assessments.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread db_lib/GoGitClient.go
@@ -42,12 +42,14 @@ func (c GoGitClient) getAuthMethod(r GitRepository) (transport.AuthMethod, error
switch r.Repository.SSHKey.Type {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: High (availability / DoS)

Repository.SSHKey is now optional, but this line still dereferences it unconditionally. For a repo with SSHKeyID == nil and a normal https:// URL, GetType() is not RepositoryLocal, so git operations call getAuthMethod, hit switch r.Repository.SSHKey.Type, and panic (nil pointer). Any project user who can create such a repo can break task execution for runners using go_git.

Fix direction: Guard the whole switch with if r.Repository.SSHKey == nil { return nil, nil } (or equivalent) before reading .Type, and treat nil key like AccessKeyNone for HTTPS.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Security review (PR #3826)

Outcome: One medium finding remains: a nil-pointer path in GoGitClient.getAuthMethod when a repository has no SSH key (nullable ssh_key_id). Other changes (runner payload filtering, migration PRAGMA foreign_keys, backup/restore) do not introduce a plausible auth bypass or injection in reviewed paths.

Notable non-security note: Repository.SSHKeyID still carries binding:"required" while the DB column is now nullable—API validation may be inconsistent with the schema (behavioral, not classified as a vuln here).

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread db_lib/GoGitClient.go
@@ -42,12 +42,14 @@ func (c GoGitClient) getAuthMethod(r GitRepository) (transport.AuthMethod, error
switch r.Repository.SSHKey.Type {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium — denial of service (nil dereference)

Repositories can now have ssh_key_id / SSHKey unset. This function still does switch r.Repository.SSHKey.Type and later dereferences r.Repository.SSHKey (e.g. SSH branch). If SSHKey is nil, the server panics on clone/pull/list branches for that repo.

Impact: Any user who can create/update a repo to omit the key (or any code path that loads such a row) can trigger repeated crashes against endpoints using the Go Git client (e.g. branch listing), affecting availability.

Fix direction: Guard at the top of getAuthMethod (nil SSHKeyreturn nil, nil or explicit error) before the switch, and ensure SSH/HTTP branches never dereference nil.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review (PR 3826)

Outcome: One medium finding related to the new SQLite migration path.

The nullable ssh_key_id / pointer refactors and runner payload changes were reviewed for authz bypasses, nil dereferences, and secret exposure. Those paths look like intentional hardening (guarding deserialization and map lookups when no key is bound). No high/critical issues identified there.

Finding: ApplyMigration now turns SQLite foreign_keys off before the migration transaction, but several error returns between that point and the successful Commit exit without turning enforcement back on. Any caller that reuses the same DB connection after a failed migration can run with foreign keys disabled, weakening referential integrity and making it easier for bugs or abuse to leave inconsistent rows (e.g. dangling references) that would normally be rejected.

No automated thread IDs were available from this environment to call ResolveReviewThreads; prior automation threads were requested to be cleared via cleanup_previous on this review.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

Comment thread db/sql/migration.go
}

if d.GetDialect() == util.DbDriverSQLite {
_, err = d.Sql().Exec("PRAGMA foreign_keys = OFF")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium — integrity / defense-in-depth

PRAGMA foreign_keys = OFF is executed before Begin(), but if Begin() fails (return err at ~202) or any of the early return err paths after Rollback() (~213–214, ~247–248, ~253–254) run, the connection never reaches the new PRAGMA foreign_keys = ON block (post-commit). SQLite keeps FK enforcement off for that connection until something else turns it on.

Impact: After a failed migration, subsequent operations on the same pool connection can insert/update rows that violate FK constraints, weakening DB integrity and complicating exploitation of other bugs.

Fix direction: defer a function that sets foreign_keys = ON when SQLite, or use a small helper that always restores on every exit path (including Begin failure and rollbacks).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant